home *** CD-ROM | disk | FTP | other *** search
/ Magnum One / Magnum One (Mid-American Digital) (Disc Manufacturing).iso / d18 / turbotut.arc / MANUAL.EXE / lha / CHAP12.TXT < prev    next >
Text File  |  1988-11-27  |  22KB  |  520 lines

  1.               CHAPTER 12 - Pointers and Dynamic Allocation
  2.  
  3.  
  4.  
  5.             For  certain  types of programs,  pointers  and  dynamic
  6.         allocation can be a tremendous advantage,  but most programs
  7.         do not need such a high degree of data structure.   For that
  8.         reason,  it  would probably be to your advantage to  lightly
  9.         skim over these topics and come back to them later when  you
  10.         have  a  substantial base of Pascal programming  experience.
  11.         It would be good to at least skim over this material  rather
  12.         than  completely neglecting it,  so you will have an idea of
  13.         how  pointers and dynamic allocation work and that they  are
  14.         available for your use when needed.
  15.  
  16.             A  complete understanding of this material will  require
  17.         deep  concentration  as it is very complex and  not  at  all
  18.         intuitive.   Nevertheless,  if you pay close attention,  you
  19.         will have a good grasp of pointers and dynamic allocation in
  20.         a short time.
  21.  
  22.                 WHAT ARE POINTERS, AND WHAT GOOD ARE THEY?
  23.  
  24.             If  you  examine POINTERS,  you will see a very  trivial
  25.         example  of  pointers and how they are  used.   In  the  VAR
  26.         declaration, you will see that the two variables have a ^ in
  27.         front  of  their respective types.   These are not  actually
  28.         variables,  instead,  they  point to  dynamically  allocated
  29.         variables  that  have  not been defined yet,  and  they  are
  30.         called pointers.
  31.  
  32.             The  pointer  "my_name" is a pointer to a  20  character
  33.         string  and is therefore not a variable into which  a  value
  34.         can be stored.   This is a very special Pascal TYPE,  and it
  35.         cannot be assigned a character string,  only a pointer value
  36.         or  address.   The  pointer  actually points to  an  address
  37.         somewhere  within the computer memory,  and can  access  the
  38.         data stored at that address.
  39.  
  40.             Your computer has some amount of memory installed in it.
  41.         If it is an IBM-PC or compatible,  it can have up to 640K of
  42.         RAM which is addressable by various programs.  The operating
  43.         system requires about 60K of the total, and if you are using
  44.         TURBO  Pascal  it  requires about  35K.   The  TURBO  Pascal
  45.         program  can  use  up to 64K.   Adding those  three  numbers
  46.         together  results  in  about  159K.   Any  memory  you  have
  47.         installed  in excess of that is available for the stack  and
  48.         the  heap.    The  stack  is  a  standard  DOS  defined  and
  49.         controlled  area that can grow and shrink as  needed.   Many
  50.         books  are  available  to  define  the  stack  if  you   are
  51.         interested in more information on it.
  52.  
  53.  
  54.  
  55.  
  56.  
  57.                                  Page 60
  58.  
  59.  
  60.  
  61.  
  62.  
  63.  
  64.  
  65.  
  66.  
  67.               CHAPTER 12 - Pointers and Dynamic Allocation
  68.  
  69.  
  70.             The  heap  is  a  Pascal defined  entity  that  utilizes
  71.         otherwise   unused  memory  to  store   data.    It   begins
  72.         immediately  following  the program and grows  as  necessary
  73.         upward toward the stack which is growing downward.   As long
  74.         as they never meet,  there is no problem.   If they meet,  a
  75.         run-time error is generated.   The heap is therefore outside
  76.         of  the 64K limitation of TURBO Pascal and many other Pascal
  77.         compilers.
  78.  
  79.             If you did not understand the last two paragraphs, don't
  80.         worry.  Simply remember that dynamically allocated variables
  81.         are  stored  on  the  heap  and do  not  count  in  the  64K
  82.         limitation placed upon you by some compilers.
  83.  
  84.             Back to our example program, POINTERS.  When we actually
  85.         begin executing the program,  we still have not defined  the
  86.         variables  we  wish  to use to store  data  in.   The  first
  87.         executable  statement  generates a variable for us  with  no
  88.         name  and stores it on the heap.   Since it has no name,  we
  89.         cannot do anything with it,  except for the fact that we  do
  90.         have  a pointer "my_name" that is pointing to it.   By using
  91.         the pointer, we can store up to 20 characters in it, because
  92.         that is its type, and later go back and retrieve it.
  93.  
  94.                         WHAT IS DYNAMIC ALLOCATION?
  95.  
  96.             The  variable  we have just described is  a  dynamically
  97.         allocated  variable  because  it was not defined  in  a  VAR
  98.         declaration,   but  with  a  "new"  procedure.    The  "new"
  99.         procedure  creates  a variable of the type  defined  by  the
  100.         pointer,  puts  it  on  the heap,  and finally  assigns  the
  101.         address  of  the  variable  to  the  pointer  itself.   Thus
  102.         "my_name"  contains the address of the  variable  generated.
  103.         The variable itself is referenced by using the pointer to it
  104.         followed  by a ^,  and is read,  "the variable to which  the
  105.         pointer points".
  106.  
  107.             The  next  statement assigns a place on the heap  to  an
  108.         INTEGER  type  variable  and puts its address  in  "my_age".
  109.         Following  the  "new"  statements  we  have  two  assignment
  110.         statements  in  which  the  two  variables  pointed  at  are
  111.         assigned values compatible with their respective types,  and
  112.         they  are both written out to the video display.   The  last
  113.         two statements are illustrations of the way the  dynamically
  114.         allocated variables are removed from use.   When they are no
  115.         longer  needed,  they  are  disposed of with  the  "dispose"
  116.         procedure.
  117.  
  118.             In   such   a  simple  program,   pointers   cannot   be
  119.         appreciated,  but it is necessary for a simple illustration.
  120.         In a large,  very active program,  it is possible to  define
  121.  
  122.  
  123.                                  Page 61
  124.  
  125.  
  126.  
  127.  
  128.  
  129.  
  130.  
  131.  
  132.  
  133.               CHAPTER 12 - Pointers and Dynamic Allocation
  134.  
  135.  
  136.         many variables,  dispose of some of them,  define more,  and
  137.         dispose of more, etc.  Each time some variables are disposed
  138.         of,  their  space  is  then made  available  for  additional
  139.         variables defined with the "new" procedure.
  140.  
  141.             The  heap can be made up of any assortment of variables,
  142.         they  do  not have to all be the same.   One thing  must  be
  143.         remembered,  anytime a variable is defined,  it will have  a
  144.         pointer  pointing to it.   The pointer is the only means  by
  145.         which  the variable can be accessed.   If the pointer to the
  146.         variable is lost or changed, the data itself is lost for all
  147.         practical purposes.
  148.  
  149.                        DYNAMICALLY STORING RECORDS;
  150.  
  151.             The next example program,  DYNREC, is a repeat of one we
  152.         studied  in an earlier chapter.   For your own  edification,
  153.         review the example program BIGREC before going ahead in this
  154.         chapter.   Assuming  that you are back in DYNREC,  you  will
  155.         notice  that this program looks very similar to the  earlier
  156.         one,  and in fact they do exactly the same thing.   The only
  157.         difference  in  the TYPE declaration is the  addition  of  a
  158.         pointer "person_id",  and in the VAR declaration,  the first
  159.         four  variables  are  defined as  pointers  here,  and  were
  160.         defined as record variables in the last program.
  161.  
  162.                   WE JUST BROKE THE GREAT RULE OF PASCAL
  163.  
  164.             Notice   in  the  TYPE  declaration  that  we  used  the
  165.         identifier "person" before we defined it,  which is  illegal
  166.         to  do in Pascal.   Foreseeing the need to define a  pointer
  167.         prior  to  the record,  the designers of Pascal allow us  to
  168.         break  the rule in this one place.   The pointer could  have
  169.         been defined after the record in this case,  but it was more
  170.         convenient  to  put  it before,  and  in  the  next  example
  171.         program,  it  will be required to put it before the  record.
  172.         We will get there soon.
  173.  
  174.             Since  "friend"  is  really 50  pointers,  we  have  now
  175.         defined  53 different pointers to records,  but so far  have
  176.         defined  no  variables other than "temp"  and  "index".   We
  177.         immediately define a record with "self" pointing to it,  and
  178.         use  the  pointer  so defined to fill  the  record  defined.
  179.         Compare  this  to  "BIGREC"  and you will  see  that  it  is
  180.         identical  except  for the addition of the "new" and  adding
  181.         the  ^  to  each use of the pointer to  designate  the  data
  182.         pointed to.
  183.  
  184.  
  185.  
  186.  
  187.  
  188.  
  189.                                  Page 62
  190.  
  191.  
  192.  
  193.  
  194.  
  195.  
  196.  
  197.  
  198.  
  199.               CHAPTER 12 - Pointers and Dynamic Allocation
  200.  
  201.  
  202.                         THIS IS A TRICK, BE CAREFUL
  203.  
  204.             Now  go down to the place where "mother" is  assigned  a
  205.         record and is then pointing to the record.  It seems an easy
  206.         +thing to do then to simply assign all of the values of self
  207.         to  all the values of mother as shown in the next statement,
  208.         but it doesn't work.   All the statement does,  is make  the
  209.         pointer  "mother"  point to the same place where  "self"  is
  210.         pointing.   The  data  that  was allocated  to  the  pointer
  211.         "mother"  is  now somewhere on the heap,  but we don't  know
  212.         where, so we cannot find it, use it, or deallocate it.  This
  213.         is an example of losing data on the heap.  The proper way is
  214.         given  in  the  next  two statements  where  all  fields  of
  215.         "father"  are  defined by all fields of  "mother"  which  is
  216.         pointing  at  the original "self" record.   Note that  since
  217.         "mother"  and "self" are both pointing at the  same  record,
  218.         changing  the  data with either pointer results in the  data
  219.         appearing to be changed in both because there is,  in  fact,
  220.         only one field.
  221.  
  222.             In  order  to  WRITE  from or READ  into  a  dynamically
  223.         assigned  record it is necessary to use a  temporary  record
  224.         since  dynamically  assigned records are not allowed  to  be
  225.         used in I/O statements.   This is illustrated in the section
  226.         of the program that writes some data to the monitor.
  227.  
  228.             Finally,   the   dynamically  allocated  variables   are
  229.         disposed  of  prior  to ending the program.   For  a  simple
  230.         program such as this, it is not necessary to dispose of them
  231.         because all dynamic variables are disposed of  automatically
  232.         when  the  program  is  terminated.    Notice  that  if  the
  233.         "dispose(mother)" statement was included in the program, the
  234.         data  could  not be found due to the lost pointer,  and  the
  235.         program would be unpredictable, probably leading to a system
  236.         crash.
  237.  
  238.                        SO WHAT GOOD IS THIS ANYWAY?
  239.  
  240.             Remember  when  you were initially studying  BIGREC?   I
  241.         suggested  that you see how big you could make the  constant
  242.         "number_of_friends" before you ran out of memory.   At  that
  243.         time  we  found that it could be made slightly greater  than
  244.         1000   before  we  got  the  memory  overflow   message   at
  245.         compilation.  Try the same thing with DYNREC to see how many
  246.         records  it  can handle,  remembering that the  records  are
  247.         created dynamically,  so you will have to run the program to
  248.         actually run out of memory.  The final result will depend on
  249.         how  much  memory you have installed,  and how  many  memory
  250.         resident programs you are using such as "Sidekick".   If you
  251.         have  a  full  memory of 640K,  I would  suggest  you  start
  252.         somewhere above 8000 records of "friend".
  253.  
  254.  
  255.                                  Page 63
  256.  
  257.  
  258.  
  259.  
  260.  
  261.  
  262.  
  263.  
  264.  
  265.               CHAPTER 12 - Pointers and Dynamic Allocation
  266.  
  267.  
  268.  
  269.             Now   you  should  have  a  good  idea  of  why  Dynamic
  270.         Allocation can be used to greatly increase the usefulness of
  271.         your programs.   There is, however, one more important topic
  272.         we  must cover on dynamic allocation.   That is  the  linked
  273.         list.
  274.  
  275.                           WHAT IS A LINKED LIST?
  276.  
  277.             Understanding and using a linked list is by far the most
  278.         baffling  topic  you will confront in Pascal.   Many  people
  279.         simply  throw up their hands and never try to use  a  linked
  280.         list.   I  will  try to help you understand it by use of  an
  281.         example  and  lots  of  explanation.   Examine  the  program
  282.         LINKLIST for an example of a linked list.   I tried to  keep
  283.         it  short  so you could see the entire operation and yet  do
  284.         something meaningful.
  285.  
  286.             To begin with,  notice that there are two TYPEs defined,
  287.         a pointer to the record and the record itself.   The record,
  288.         however,  has one thing about it that is new to us, the last
  289.         entry, "next" is a pointer to this very record.  This record
  290.         then,  has  the ability to point to itself,  which would  be
  291.         trivial  and meaningless,  or to another record of the  same
  292.         type  which  would be extremely useful in  some  cases.   In
  293.         fact,  this is the way a linked list is used.   I must point
  294.         out, that the pointer to another record, in this case called
  295.         "next",  does  not have to be last in the list,  it  can  be
  296.         anywhere it is convenient for you.
  297.  
  298.             A couple of pages ago, we discussed the fact that we had
  299.         to  break  the  great rule of Pascal and use  an  identifier
  300.         before it was defined.   This is the reason the exception to
  301.         the  rule  was allowed.   Since the pointer  points  to  the
  302.         record,  and the record contains a reference to the pointer,
  303.         one  has  to be defined after being used,  and by  rules  of
  304.         Pascal,  the pointer can be defined first, provided that the
  305.         record  is  defined  immediately following it.   That  is  a
  306.         mouthful  but  if  you  just use the  syntax  shown  in  the
  307.         example, you will not get into trouble with it.
  308.  
  309.                             STILL NO VARIABLES?
  310.  
  311.             It may seem strange, but we still will have no variables
  312.         defined,  except  for our old friend "index".   In fact  for
  313.         this example,  we will only define 3 pointers.   In the last
  314.         example  we  defined 54 pointers,  and had lots  of  storage
  315.         room.  Before we are finished, we will have at least a dozen
  316.         pointers but they will be stored in our records, so they too
  317.         will be dynamically allocated.
  318.  
  319.  
  320.  
  321.                                  Page 64
  322.  
  323.  
  324.  
  325.  
  326.  
  327.  
  328.  
  329.  
  330.  
  331.               CHAPTER 12 - Pointers and Dynamic Allocation
  332.  
  333.  
  334.             Lets look at the program itself now.  First, we create a
  335.         dynamically  allocated record and define it by  the  pointer
  336.         "place_in_list".   It  is composed of the three data fields,
  337.         and another pointer.   We define "start_of_list" to point to
  338.         the  first record created,  and we will leave  it  unchanged
  339.         throughout  the program.   The pointer "start_of_list"  will
  340.         always point to the first record in the linked list which we
  341.         are building up.
  342.  
  343.             We  define  the three variables in the record to be  any
  344.         name  we  desire  for illustrative  purposes,  and  set  the
  345.         pointer in the record to NIL.   NIL is a reserved word  that
  346.         doesn't  put  an  address in the pointer but defines  it  as
  347.         empty.  A pointer that is currently NIL cannot be written to
  348.         the  display as it has no value,  but it can be tested in  a
  349.         logical  statement to see if it is NIL.   It is therefore  a
  350.         dummy  assignment.   With all of that,  the first record  is
  351.         completely defined.
  352.  
  353.                         DEFINING THE SECOND RECORD
  354.  
  355.              When  you  were young you may have played  a  searching
  356.         game  in which you were given a clue telling you  where  the
  357.         next clue was at.   The next clue had a clue to the location
  358.         of  the third clue.   You kept going from clue to clue until
  359.         you  found the prize.   You simply exercised a linked  list.
  360.         We  will now build up the same kind of a list in which  each
  361.         record will tell us where the next record is at.
  362.  
  363.             We will now define the second record.   Our goal will be
  364.         to store a pointer to the second record in the pointer field
  365.         of  the first record.   In order to keep track of  the  last
  366.         record,  the one in which we need to update the pointer,  we
  367.         will  keep  a  pointer to it in "temp_place".   Now  we  can
  368.         create another "new" record and use "place_in_list" to point
  369.         to  it.   Since  "temp_place" is now pointing at  the  first
  370.         record,  we  can  use it to store the value of  the  pointer
  371.         which  points to the new record.   The 3 data fields of  the
  372.         new record are assigned nonsense data for our  illustration,
  373.         and the pointer field of the new record is assigned NIL.
  374.  
  375.             Lets review our progress to this point.  We now have the
  376.         first record with a name and a pointer to the second record,
  377.         and  a  second  record with a different name and  a  pointer
  378.         assigned NIL.   We also have three pointers, one pointing to
  379.         the first record,  one pointing to the last record,  and one
  380.         we  used  just  to get here since it  is  only  a  temporary
  381.         pointer.   If you understand what is happening so far,  lets
  382.         go  on to add some additional records to the list.   If  you
  383.         are confused, go back over this material again.
  384.  
  385.  
  386.  
  387.                                  Page 65
  388.  
  389.  
  390.  
  391.  
  392.  
  393.  
  394.  
  395.  
  396.  
  397.               CHAPTER 12 - Pointers and Dynamic Allocation
  398.  
  399.  
  400.                              TEN MORE RECORDS
  401.  
  402.             The  next section of code is contained within a FOR loop
  403.         so  the statements are simply repeated ten  times.   If  you
  404.         observe  carefully,  you will notice that the statements are
  405.         identical  to the second group of statements in the  program
  406.         (except of course for the name assigned).   They operate  in
  407.         exactly  the same manner,  and we end up with ten more names
  408.         added  to  the list.   You will now see  why  the  temporary
  409.         pointer was necessary,  but pointers are cheap, so feel free
  410.         to use them at will. A pointer only uses 4 bytes of memory.
  411.  
  412.             We  now have generated a linked list of twelve  entries.
  413.         We  have a pointer pointing at the first entry,  and another
  414.         pointer pointing at the last.   The only data stored  within
  415.         the program itself are three pointers,  and one integer, all
  416.         of  the  data is on the heap.   This is one advantage  to  a
  417.         linked list,  it uses very little internal memory, but it is
  418.         costly  in  terms of programming.   You should never  use  a
  419.         linked  list  simply  to save memory,  but  only  because  a
  420.         certain  program  lends  itself well to  it.   Some  sorting
  421.         routines are extremely fast because of using a linked  list,
  422.         and it could be advantageous to use in a database.
  423.  
  424.                       HOW DO WE GET TO THE DATA NOW?
  425.  
  426.             Since  the data is in a list,  how can we get a copy  of
  427.         the  fourth entry for example?   The only way is to start at
  428.         the beginning of the list and successively examine  pointers
  429.         until  you  reach the desired one.   Suppose you are at  the
  430.         fourth and then wish to examine the third.   You cannot back
  431.         up,  because  you didn't define the list that way,  you  can
  432.         only  start at the beginning and count to  the  third.   You
  433.         could  have  defined  the  record  with  two  pointers,  one
  434.         pointing forward,  and one pointing backward.  This would be
  435.         a  doubly-linked  list and you could then go  directly  from
  436.         entry four to entry three.
  437.  
  438.             Now that the list is defined, we will read the data from
  439.         the  list and display it on the video monitor.   We begin by
  440.         defining the pointer,  "place_in_list",  as the start of the
  441.         list.   Now  you see why it was important to keep a copy  of
  442.         where the list started.   In the same manner as filling  the
  443.         list,  we  go from record to record until we find the record
  444.         with NIL as a pointer.
  445.  
  446.             There are entire books on how to use linked  lists,  and
  447.         most Pascal programmers will seldom, if ever, use them.  For
  448.         this  reason,  additional detail is considered  unnecessary,
  449.         but  to be a fully informed Pascal programmer,  some insight
  450.         is necessary.
  451.  
  452.  
  453.                                  Page 66
  454.  
  455.  
  456.  
  457.  
  458.  
  459.  
  460.  
  461.  
  462.  
  463.               CHAPTER 12 - Pointers and Dynamic Allocation
  464.  
  465.  
  466.  
  467.                            PROGRAMMING EXERCISE
  468.  
  469.         1.  Write  a program to store a few names dynamically,  then
  470.             display  the stored names on the monitor.  As your first
  471.             exercise in dynamic allocation, keep it very simple.
  472.  
  473.  
  474.  
  475.  
  476.  
  477.  
  478.  
  479.  
  480.  
  481.  
  482.  
  483.  
  484.  
  485.  
  486.  
  487.  
  488.  
  489.  
  490.  
  491.  
  492.  
  493.  
  494.  
  495.  
  496.  
  497.  
  498.  
  499.  
  500.  
  501.  
  502.  
  503.  
  504.  
  505.  
  506.  
  507.  
  508.  
  509.  
  510.  
  511.  
  512.  
  513.  
  514.  
  515.  
  516.  
  517.  
  518.  
  519.                                  Page 67
  520.